package com.octopus.algorithm;

import com.octopus.algorithm.BasicDigit.UnSupportZeroOrNegativeDigit;
import com.octopus.string.StringUtils;

public class Digit52 {

	private static char convertIntToCharForDigit52(int intValue) throws ValueOutofRangeExceptionDigit52 {
		if (intValue >= 0 && intValue <= 25) {
			return (char) (intValue + 65);
		}
		if (intValue >= 26 && intValue <= 51) {
			return (char) (intValue + 70);
		}
		throw new ValueOutofRangeExceptionDigit52(intValue);
	}

	private static int convertCharToIntForDigit52(char charValue) throws CharValueOutofRangeExceptionDigit52 {
		int intValue = (int) charValue;
		if (intValue >= 65 && intValue <= 90) {
			return intValue - 65;
		}
		if (intValue >= 97 && intValue <= 121) {
			return intValue - 70;
		}
		throw new CharValueOutofRangeExceptionDigit52(charValue);
	}
	
	public static class ValueOutofRangeExceptionDigit52 extends Exception{
		
		private static final long serialVersionUID = 1L;
		private int value;
		public ValueOutofRangeExceptionDigit52(int value){
			this.value = value;
		}
		public String toString(){
			return StringUtils.concat(String.valueOf(this.value), " is not between 0 and 51.");
		}
	}
	
	public static class CharValueOutofRangeExceptionDigit52 extends Exception{
		
		private static final long serialVersionUID = 1L;
		private char value;
		public CharValueOutofRangeExceptionDigit52(char value){
			this.value = value;
		}
		public String toString(){
			return StringUtils.concat(String.valueOf(this.value), " should be a-z or A-Z");
		}
	}

	public static String toDigit52StringPosOnly(long number){
		StringBuffer sb = new StringBuffer();
		int[] convertedArray = null;
		try {
			convertedArray = BasicDigit.decToSpecDigitIntArrayPosOnly(number, 52);
		} catch (UnSupportZeroOrNegativeDigit usznd) {
			// Such exception will never be thrown.
		}
		for (int i = convertedArray.length - 1; i >= 0; i--) {
			try{
				sb.append(convertIntToCharForDigit52(convertedArray[i]));
			}catch(ValueOutofRangeExceptionDigit52 vored){
				return null;
			}
		}
		return sb.toString();
	}

	public static long digit52StringToDecPosOnly(String digit52String)
			throws NotValid52DigitsString {
		if (!digit52String.matches("[a-zA-Z]*")) {
			throw new NotValid52DigitsString(digit52String);
		}
		int stringLength = digit52String.length();
		char[] charArray = new char[stringLength];
		for (int i = 0, size = digit52String.length(); i < size; i++) {
			charArray[i] = digit52String.charAt(stringLength - i - 1);
		}

		int[] intArray = new int[charArray.length];
		
		long result = 0l;
		
		for (int i = 0, size = intArray.length; i < size; i++) {
			try{
				intArray[i] = convertCharToIntForDigit52(charArray[i]);
			}catch(CharValueOutofRangeExceptionDigit52 cvored){
				return result;
			}
		}

		try {
			result = BasicDigit.specDigitIntArrayToDecPosOnly(intArray, 52);
		} catch (UnSupportZeroOrNegativeDigit usznd) {
			// Such exception will never be thrown.
		}
		return result;
	}

	public static class NotValid52DigitsString extends Exception {
		
		private static final long serialVersionUID = 1L;
		private String dataString;

		public NotValid52DigitsString(String dataString) {
			this.dataString = dataString;
		}

		public String toString() {
			return StringUtils.concat("Not Valid 52 digits String:[",
					dataString, "]");
		}
	}

	

	public static void main(String args[]) throws NotValid52DigitsString {
		String stringValue = toDigit52StringPosOnly(2900000000000019987l);
		System.out.println(stringValue);
		System.out.println(digit52StringToDecPosOnly(stringValue));
	}

}
